package com.egghiro.framework.j2se.util;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Random;

/**
 * randomPeek()→randomPop()が同じ結果になる<br>
 * 
 * 案が2つ：<br>
 * ①Collections.shuffle()でソート。でもこれだとaddするたびにshuffleする必要がある<br>
 * ②nextIndexをローカルに持ち、add()、addAll()、randomPop()のあとそれを再生成する。<br>
 * ⇒Iteratorも必要なので、案①しかない。。。
 * 
 * @param <E>
 */
public class RandomComposite<E> implements Collection<E> {
    private SLinkedList<E> list = null;
    private Random random = null;

    // private int nextIndex = -1;// 初期化忘れた場合例外を発生されるため-1

    public RandomComposite() {
        list = new SLinkedList<E>();
        random = new Random();
    }

    public RandomComposite(Collection<E> c) {
        this();
        this.addAll(c);
    }

    /**
     * 
     * @return
     * @throws IndexOutOfBoundsException
     */
    public E randomPeek() throws IndexOutOfBoundsException {
//        return list.get(this.nextIndex);
        return this.list.peek();
    }

    /**
     * 
     * @return
     * @throws IndexOutOfBoundsException
     */
    public E randomPop() throws IndexOutOfBoundsException {
//        E element = list.remove(this.nextIndex);
//        this.generateNextIndex();
//        return element;
        return this.list.pop();
    }

    public boolean add(E e) {
        boolean b = list.add(e);
//        this.generateNextIndex();
        this.shuffle();
        return b;
    }

    public boolean addAll(Collection<? extends E> c) {
        boolean b = list.addAll(c);
//        this.generateNextIndex();
        this.shuffle();
        return b;
    }

    public int size() {
        return list.size();
    }

    public void clear() {
        list.clear();
    }

    public boolean contains(Object obj) {
        return list.contains(obj);
    }

    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public Iterator<E> iterator() {
        return list.iterator();
    }

    public boolean remove(Object obj) {
        return list.remove(obj);
    }

    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    public Object[] toArray() {
        return list.toArray();
    }

    public <T> T[] toArray(T[] array) {
        return list.toArray(array);
    }

    public void shuffle() {
        this.shuffle(this.random);
    }

    public void shuffle(Random random) {
        Collections.shuffle(this.list, random);
    }

    // private void generateNextIndex() {
    // this.nextIndex = random.nextInt(list.size());
    // }
}
